#include "ResourceManager.h"


ResourceManager::ResourceManager(string str)
	:Component(COMP_RESOURCE),
	m_resMap(str),
	m_resMapping(),
	m_meshLoader(),
	m_modelLoader(),
	m_textureLoader()
{
	m_dumpFile.open(RESOURCE_DUMP_FILENAME,fstream::trunc|fstream::out);
	if(!m_dumpFile.is_open())
	{
		EXCEPTION("Dump file can not found.")
	}
}


ResourceManager::~ResourceManager(void)
{
	m_dumpFile.close();
}

void ResourceManager::AddedToObject()
{
	RequestMessage(MSG_INITIAL,&ResourceManager::Initial);
	RequestMessage(MSG_GET_RESOURCE,&ResourceManager::GetResource);
	RequestMessage(MSG_REMOVE_RESOURCE,&ResourceManager::RemoveResource);
	RequestMessage(MSG_REMOVE_ALL_RESOURCE,&ResourceManager::RemoveAllResource);
	RequestMessage(MSG_DUMP_ALL_MESSAGE,&ResourceManager::Dump);
}

void ResourceManager::Initial(const Message& msg)
{
	try
	{
		m_meshLoader=boost::make_shared<MeshLoader>(this);
		m_modelLoader=boost::make_shared<ModelLoader>(this);
		m_textureLoader=boost::make_shared<TextureLoader>(this);
		m_resMapping=boost::make_shared<ResourceMapping>(m_resMap);
		AddLocalComponent(m_meshLoader);
		AddLocalComponent(m_modelLoader);
		AddLocalComponent(m_resMapping);
		AddLocalComponent(m_textureLoader);
	}
	catch(std::exception& e)
	{
		
	}
}

void ResourceManager::AddResource(Resource::ResourceType type,string name, Resource::sPtr res)
{
	m_resourceCatalog[type][name]=res;
}

void ResourceManager::RemoveResource(const Message& msg)
{
	Resource::ResourceType type;
	string name;
	AuxUnGroupArgus(msg.p,type,name);
	if(m_resourceCatalog[type].find(name)!=m_resourceCatalog[type].end())
		m_resourceCatalog[type].erase(name);
	else
		EXCEPTION("Resource not found")
}

bool ResourceManager::IsLoaded(Resource::ResourceType type,string name)
{
	if(m_resourceCatalog[type].find(name)!=m_resourceCatalog[type].end())
		return true;
	else
		return false;
}

void ResourceManager::RemoveAllResource(const Message& msg)
{
	for(ResourceCatalog::iterator iter=m_resourceCatalog.begin();iter!=m_resourceCatalog.end();iter++)
	{
		iter->second.clear();
	}
}

Resource::sPtr ResourceManager::GetResource(Resource::ResourceType type, string name)
{
	return m_resourceCatalog[type][name];
}

/*
This function is a little confuse.
Should auto load the resource when this res not found in the map ?
The auto-load feature seems redundant.
Because ResourceMananger can not load the resource by it-self prettily.
Engine always use ModelLoader, MeshLoader ... to load the resource.
*/
void ResourceManager::GetResource(const Message& msg)
{
	Resource::sPtr* res;
	Resource::ResourceType type;
	string name;
	string path;
	AuxUnGroupArgus(msg.p,name,type,res);
	if(m_resourceCatalog[type].find(name)!=m_resourceCatalog[type].end())
	{
		*res=m_resourceCatalog[type][name];
	}
	/*else
	{
		path=m_resMapping->GetPath(name);
		if(path!="")
		{
			if(type==Resource::MEMORY)
			{
				Resource::sPtr tmp=boost::make_shared<Resource>();
				tmp->data=AuxGroupArgus(path);
				m_resourceCatalog[type][name]=tmp;
				*res=tmp;
			}
		}
		else
		{
			EXCEPTION("")
		}
	}*/

}

void ResourceManager::Dump(const Message& msg)
{
	if(!m_dumpFile.is_open())
	{
		EXCEPTION("Can not open the resource log file!")
	}
	for(ResourceCatalog::iterator iter=m_resourceCatalog.begin();iter!=m_resourceCatalog.end();iter++)
	{
		ResourceMap preMap=iter->second;
		m_dumpFile<<"Catalog:";
		DumpCatalog(iter->first);
		m_dumpFile<<endl;
		for(ResourceMap::iterator iiter=preMap.begin();iiter!=preMap.end();iiter++)
		{
			m_dumpFile<<"\t"<<iiter->first<<endl;
		}
	}
}

void ResourceManager::DumpCatalog(Resource::ResourceType rt)
{
	switch(rt)
	{
	case Resource::BUFFER:
		m_dumpFile<<"Buffer";
		break;
	case Resource::MATERIAL:
		m_dumpFile<<"Material";
		break;
	case Resource::MESH:
		m_dumpFile<<"Mesh";
		break;
	case Resource::TEXTURE:
		m_dumpFile<<"TEXTURE";
		break;
	default:
		m_dumpFile<<"UNKNOWN";
		break;
	}
}